package de.hatraco.funderberg.blackjack.controller;

import de.hatraco.funderberg.blackjack.data.DataMISC;
import de.hatraco.funderberg.blackjack.data.GraphicsBlackJack;
import de.hatraco.funderberg.blackjack.model.Game;
import de.hatraco.funderberg.blackjack.utils.TimerActionListener;
import de.hatraco.funderberg.blackjack.views.*;
import javax.swing.*;

public class Ctrl_Dialogs {
	
	//Singleton Pattern: Stellt sicher, dass nur eine Instanz von Ctrl_Dialogs existiert
	private static Ctrl_Dialogs instance = new Ctrl_Dialogs();
	
	public static Ctrl_Dialogs getInstance() {
		if (instance == null) {
			instance = new Ctrl_Dialogs();
		}	
		return instance;
	}
	
	private Ctrl_MainView ctrl_mainview;
	private StartDialog startdialog;
	private NamesDialog namesdialog;
	private StartstackDialog startstackdialog;
	private BetDialog betdialog;
	//private RulesDialog rulesdialog;
	private InfoDialog infodialog;
	private ResultsDialog resultsdialog;
	//private OutofstackDialog outofstackdialog;
	//private ResolutionDialog resolutiondialog;
	private Game game;
	private GraphicsBlackJack img;
	
	private int counter_startThegame;
	private int counter_getTheStartstack2;
	private int counter_benderwalks;
	private int counter_showNextPlayer;
	private int counter_showNextDealer;
	private int counter_showResults;
	
	private Timer timer_startThegame;
	private Timer timer_getTheStartstack2;
	private Timer timer_benderwalks;
	private Timer timer_showNextPlayer;
	private Timer timer_showNextDealer;
	private Timer timer_showResults;	
	
	String link = DataMISC.LINKIMG;	

	public Ctrl_Dialogs() {
		
		//Instanziert Models, Views, Controller und Timer
		this.ctrl_mainview = Ctrl_MainView.getInstance();
		this.startdialog = StartDialog.getInstance();
		this.namesdialog = NamesDialog.getInstance();
		this.startstackdialog = StartstackDialog.getInstance();
		this.betdialog = BetDialog.getInstance();
		//this.rulesdialog = RulesDialog.getInstance();
		this.infodialog = InfoDialog.getInstance();
		this.resultsdialog = ResultsDialog.getInstance();
		//this.outofstackdialog = OutofstackDialog.getInstance();
		//this.resolutiondialog = ResolutionDialog.getInstance();
		this.game = Game.getInstance();
		this.img = GraphicsBlackJack.getInstance();
		
		this.timer_startThegame = new Timer(1000, new TimerActionListener());
		this.timer_getTheStartstack2 = new Timer(10, new TimerActionListener());
		this.timer_benderwalks = new Timer(120, new TimerActionListener());
		this.timer_showNextPlayer = new Timer(2000, new TimerActionListener());
		this.timer_showNextDealer = new Timer(2000, new TimerActionListener());
		this.timer_showResults = new Timer(2000, new TimerActionListener());
	}
	
	//Öffnet den StartDialog und spielt die Bwalks_start-Animation ab
	public void startGame() {
		counter_startThegame = 0;
		showDialog(startdialog);
		startdialog.getBg_start().setIcon(img.getBwalks_start());
		timer_startThegame.setInitialDelay(6500);
		timer_startThegame.start();
	}
	
	//Schließt den StartDialog und öffnet den NamesDialog
	public void switchToNames() {
		closeDialog(startdialog);
		showDialog(namesdialog);
	}
	
//TODO wird über die Buttons im Main_Controller erledigt, oder?	
//	public void setNames() {
//		if (game.getPl_quant() > namesdialog.getCount() + 1) {
//			int i = namesdialog.getCount();
//			try {
//				game.getPlayers().get(i).setName(namesdialog.getName_input().getText());
//			} catch (NumberFormatException e) {
//				// TODO Auto-generated catch block
//			}
//			ctrl_mainview.setName(i);
//			namesdialog.getNames_player().setText("Spieler " + (String.valueOf(i + 2)));
//			namesdialog.getName_input().setText("");
//			namesdialog.setCount(i + 1);
//		} 
//		else {
//			int i = namesdialog.getCount();
//			try {
//				game.getPlayers().get(i).setName(namesdialog.getName_input().getText());
//			} catch (NumberFormatException e) {
//				// TODO Auto-generated catch block
//			}
//			ctrl_mainview.setName(i);
//			namesdialog.setCount(0);
//			closeDialog(namesdialog);
//			showDialog(startstackdialog);
//		}
//	}
	
	//Deaktiviert und aktiviert JLabels im StartstackDialog
	public void getTheStartstack1() {
		startstackdialog.getStartstack_text1().setVisible(false);
		startstackdialog.getStartstack_text2().setVisible(false);
		startstackdialog.getStartstack_text3().setVisible(false);
		startstackdialog.getStartstack_text4().setVisible(false);
		startstackdialog.getStartstack_text5().setVisible(false);
		startstackdialog.getStartstack_ok().setVisible(false);
		startstackdialog.getThestartstack().setVisible(true);
		getTheStartstack2();
	}
	
	//Startet die Ermittlung des Startstacks (über Timer)
	public void getTheStartstack2() { 
		counter_getTheStartstack2 = 0;
		timer_getTheStartstack2.start();
	}	
	
	//Aktiviert weitere JLabels
	public void getTheStartstack3() {
		startstackdialog.getStartstack_text6().setVisible(true);
		startstackdialog.getStartstack_text7().setVisible(true);
		startstackdialog.getStartstack_text8().setVisible(true);
		startstackdialog.getStartstack_start().setVisible(true);
	}
	
	//Deaktivert JLabels und startet die BenderWalks-Animation
	public void benderWalks() {
		startstackdialog.getStartstack_text6().setVisible(false);
		startstackdialog.getStartstack_text7().setVisible(false);
		startstackdialog.getStartstack_text8().setVisible(false);
		startstackdialog.getStartstack_start().setVisible(false);
		startstackdialog.getThestartstack().setVisible(false);
		counter_benderwalks = 0;
		startstackdialog.getBg_startstack().setIcon(img.getBwalks());
		timer_benderwalks.setInitialDelay(5000);
		timer_benderwalks.start();
	}
	
	//Methode zur Erhöhung der Bet um amount
	public void raiseBet(int amount) {
		//Prüft, ob der Stack groß genug ist
		if ((game.getPlayers().get(game.getPl_on()).getBet() + amount) <= game.getPlayers().get(game.getPl_on()).getStack()) {
			//Falls ja: Bet = Bet + amount
			game.getPlayers().get(game.getPl_on()).setBet((game.getPlayers().get(game.getPl_on()).getBet() + amount));
		//Falls nein: Bet = Stack	
		} else {
			game.getPlayers().get(game.getPl_on()).setBet((game.getPlayers().get(game.getPl_on()).getStack()));
		}
		//Anzeigen der Bet im Dialog
		betdialog.getThebet().setText(String.valueOf(game.getPlayers().get(game.getPl_on()).getBet()));
	}
	
	//Methode zur Verringerung der bet um amount
	public void decrBet(int amount) {
		//Prüft, ob Bet groß genug ist
		if (game.getPlayers().get(game.getPl_on()).getBet() >= amount) {
			//Falls ja: Bet = bet - amount
			game.getPlayers().get(game.getPl_on()).setBet((game.getPlayers().get(game.getPl_on()).getBet() - amount));
			//Anzeigen der Bet im Dialog
			betdialog.getThebet().setText(String.valueOf(game.getPlayers().get(game.getPl_on()).getBet()));
		//Falls nein: bet = 0	
		} else {
			game.getPlayers().get(game.getPl_on()).setBet(0);
			//Anzeigen der Bet im Dialog
			betdialog.getThebet().setText("0");
		}
	}
	
	// TODO werden die "showNext..."-Methoden überhaupt verwendet?
	public void showNextPlayer() {
		infodialog.getNextplayer().setText(game.getPlayers().get(game.getPl_on()).getName() + " ist dran.");
		infodialog.getNextplayer().setVisible(true);
		counter_showNextPlayer = 0;
		timer_showNextPlayer.setInitialDelay(0);
		timer_showNextPlayer.start();
	}
	
	public void showNextDealer() {
		infodialog.getNextplayer().setText("Dealer ist dran.");
		infodialog.getNextplayer().setVisible(true);
		counter_showNextDealer = 0;
		timer_showNextDealer.setInitialDelay(0);
		timer_showNextDealer.start();
	}
	
	//Setzt den String "whatyouhave" eines Players für die spätere Ergebnisanzeige
	public void setWhatplayerhas() {
		//prüft, ob eine Splithand gespielt wird
		if (game.getPlayers().get(game.getPl_on()).isSplitActive() == true) {
			//holt das Ergebnis der Hand
			int r = game.getPlayers().get(game.getPl_on()).getSplithand().getResult();
			//Setzt den String in Abhängigkeit vom Ergebnis
			if (r > 21 && r < 99) {
				game.getPlayers().get(game.getPl_on()).getSplithand().setWhatyouhave("Your split hand: BUST!");
			} else if (r == 99) {
				game.getPlayers().get(game.getPl_on()).getSplithand().setWhatyouhave("Your split hand: BLACK JACK!");
			} else {
				game.getPlayers().get(game.getPl_on()).getSplithand().setWhatyouhave("Your split hand: " + r + " points.");
			}
		//Keine Splithand? -> Mainhand	
		} else {
			//holt das Ergebnis der Hand
			int r = game.getPlayers().get(game.getPl_on()).getHand().getResult();
			//Setzt den String in Abhängigkeit vom Ergebnis
			if (r > 21 && r < 99) {
				game.getPlayers().get(game.getPl_on()).getHand().setWhatyouhave("Your main hand: BUST!");
			} else if (r == 99) {
				game.getPlayers().get(game.getPl_on()).getHand().setWhatyouhave("Your main hand: BLACK JACK!");
			} else {
				game.getPlayers().get(game.getPl_on()).getHand().setWhatyouhave("Your main hand: " + r + " points.");
			}
		}	
	}
	//Setzt den String "whatdealerhas" für die spätere Ergebnisanzeige
	public void setWhatdealerhas() {
		//holt das Ergebnis der Hand
		int r = game.getDealer().getHand().getResult();
		//Setzt den String in Abhängigkeit vom Ergebnis
		if (r > 21 && r < 99) {
			game.getDealer().getHand().setWhatyouhave("Dealer has BUST!");
		} else if (r == 99) {
			game.getDealer().getHand().setWhatyouhave("Delaer has BLACK JACK!");
		} else {
			game.getDealer().getHand().setWhatyouhave("Dealer has " + r + " points.");
		}
	}
	
	//Methode für die Anzeige der Ergebnisse im ResultsDialog
	public void showResults() {
		//Holt die Ergebisse des aktiven Spielers und des Dealers
		int result_p = game.getPlayers().get(game.getPl_on()).getHand().getResult();
		int result_ps = game.getPlayers().get(game.getPl_on()).getSplithand().getResult();
		int result_d = game.getDealer().getHand().getResult();
		//Prüft, ob das Ergebis = 0 ist (= Spieler ist outofstack)
		if (result_p == 0) {
			//Falls ja: pl_on wird erhöht und die Methode erneut aufgerufen
			game.setPl_on(game.getPl_on() + 1);
			showResults();
		//Falls nein...	
		} else {
			//Resetet alle JLabels des ResultDialogs
			resultsdialog.resetLabels();
			//Öffnet den ResultDialog
			showDialog(resultsdialog);
			//Setzt und aktiviert die Labels für die Headline und die Ergebnisse des Spielers und des Dealers
			resultsdialog.getHl().setText("Result for " + game.getPlayers().get(game.getPl_on()).getName() + ":");
			resultsdialog.getPlayerhas().setText(game.getPlayers().get(game.getPl_on()).getHand().getWhatyouhave());
			resultsdialog.getDealerhas().setText(game.getDealer().getHand().getWhatyouhave());
			resultsdialog.getHl().setVisible(true);
			resultsdialog.getDealerhas().setVisible(true);
			resultsdialog.getPlayerhas().setVisible(true);
			resultsdialog.getResult_mainhand().setVisible(true);
			//Setzt die JLabels für das Resultat (Gewonnen oder Verloren) in Abhängigkeit der Ergebnisse von Spieler und Dealer
			if (result_p > 21 && result_p < 99) {
				resultsdialog.getResult_mainhand().setText("Your main hand loses! (- " + game.getPlayers().get(game.getPl_on()).getBet() + " chips)");
			} else if (result_p == 99) {
				if (result_d == 99) {
					resultsdialog.getResult_mainhand().setText("Your main hand is a draw! (+/- 0 chips)");
				} else {
					resultsdialog.getResult_mainhand().setText("Your main hand wins! (+ " + ((game.getPlayers().get(game.getPl_on()).getBet()/2)*3) + " chips)");
				}
			} else {
				if (result_p > result_d) {
					resultsdialog.getResult_mainhand().setText("Your main hand wins! (+ " + game.getPlayers().get(game.getPl_on()).getBet() + " chips)");
				} else if (result_p == result_d) {
					resultsdialog.getResult_mainhand().setText("Your main hand is a draw! (+/- 0 chips)");
				} else {
					if (result_d > 21 && result_d < 99) {
						resultsdialog.getResult_mainhand().setText("Your main hand wins! (+ " + game.getPlayers().get(game.getPl_on()).getBet() + " chips)");
					} else {
						resultsdialog.getResult_mainhand().setText("Your main hand loses! (- " + game.getPlayers().get(game.getPl_on()).getBet() + " chips)");
					}	
				}
			}
			//Prüft, ob auch eine Splithand gespielt wurde (dann ist result_ps > 0)
			if (result_ps > 0) {
				//Setzt und aktiviert die Labels für das Ergebnis der Splithand
				resultsdialog.getSplitPlayerhas().setText(game.getPlayers().get(game.getPl_on()).getSplithand().getWhatyouhave());
				resultsdialog.getSplitPlayerhas().setVisible(true);
				resultsdialog.getResult_splithand().setVisible(true);
				//Setzt die JLabels für das Resultat (Gewonnen oder Verloren) in Abhängigkeit der Ergebnisse von Spieler und Dealer
				if (result_ps > 21 && result_ps < 99) {
					resultsdialog.getResult_splithand().setText("Your split hand loses! (- " + game.getPlayers().get(game.getPl_on()).getSplitbet() + " chips)");
				} else if (result_ps == 99) {
					if (result_d == 99) {
						resultsdialog.getResult_splithand().setText("Your split hand is a draw! (+/- 0 chips)");
					} else {
						resultsdialog.getResult_splithand().setText("Your split hand wins! (+ " + ((game.getPlayers().get(game.getPl_on()).getSplitbet()/2)*3) + " chips)");
					}
				} else {
					if (result_ps > result_d) {
						resultsdialog.getResult_splithand().setText("Your split hand wins! (+ " + game.getPlayers().get(game.getPl_on()).getSplitbet() + " chips)");
					} else if (result_ps == result_d) {
						resultsdialog.getResult_splithand().setText("Your split hand is a draw! (+/- 0 chips)");
					} else {
						if (result_d > 21 && result_d < 99) {
							resultsdialog.getResult_splithand().setText("Your split hand wins! (+ " + game.getPlayers().get(game.getPl_on()).getSplitbet() + " chips)");
						} else {
							resultsdialog.getResult_splithand().setText("Your split hand loses! (- " + game.getPlayers().get(game.getPl_on()).getSplitbet() + " chips)");
						}	
					}
				}
			}
		}
		//Setzt den neuen Stack in der View
		ctrl_mainview.setStack(game.getPl_on());
		//prüft, ob noch Spieler folgen ...
		if (game.getPl_on() < (game.getPl_quant() -1)) {
			//falls einer der noch folgenden Spieler noch Chips hat, dann wird "NextPlayer" aktiv und die For-Schleife wird beendet
			for (int i = (game.getPl_on()+1); i < game.getPl_quant(); i++) {
				if (game.getPlayers().get(i).isIsoutofstack() == false) {
					resultsdialog.getNextplayer().setVisible(true);
					break;
				}
				//hat keiner der noch folgenden Spieler noch Chips, kann man die nächste Runde starten oder aufhören
				resultsdialog.getNextplayer().setVisible(false);
				resultsdialog.getNextround().setVisible(true);
				resultsdialog.getQuitgame().setVisible(true);	
			}
		//... andernfalls kann man die nächste Runde starten oder aufhören	
		} else {
			resultsdialog.getNextplayer().setVisible(false);
			resultsdialog.getNextround().setVisible(true);
			resultsdialog.getQuitgame().setVisible(true);
		}
	}
	
	//Ruft einen Dialog auf
	public void showDialog(JDialog dialog) {
		dialog.setLocationRelativeTo(MainView.getInstanceWindow());
		dialog.setVisible(true);
	}
	
	//Schließt einen Dialog
	public void closeDialog(JDialog dialog) {
		dialog.setVisible(false);
		dialog.dispose();
	}

	public int getCounter_startThegame() {
		return counter_startThegame;
	}

	public void setCounter_startThegame(int counter_startThegame) {
		this.counter_startThegame = counter_startThegame;
	}

	public int getCounter_getTheStartstack2() {
		return counter_getTheStartstack2;
	}

	public void setCounter_getTheStartstack2(int counter_getTheStartstack2) {
		this.counter_getTheStartstack2 = counter_getTheStartstack2;
	}

	public int getCounter_benderwalks() {
		return counter_benderwalks;
	}

	public void setCounter_benderwalks(int counter_benderwalks) {
		this.counter_benderwalks = counter_benderwalks;
	}

	public int getCounter_showNextPlayer() {
		return counter_showNextPlayer;
	}

	public void setCounter_showNextPlayer(int counter_showNextPlayer) {
		this.counter_showNextPlayer = counter_showNextPlayer;
	}

	public int getCounter_showNextDealer() {
		return counter_showNextDealer;
	}

	public void setCounter_showNextDealer(int counter_showNextDealer) {
		this.counter_showNextDealer = counter_showNextDealer;
	}

	public int getCounter_showResults() {
		return counter_showResults;
	}

	public void setCounter_showResults(int counter_showResults) {
		this.counter_showResults = counter_showResults;
	}

	public Timer getTimer_startThegame() {
		return timer_startThegame;
	}

	public void setTimer_startThegame(Timer timer_startThegame) {
		this.timer_startThegame = timer_startThegame;
	}

	public Timer getTimer_getTheStartstack2() {
		return timer_getTheStartstack2;
	}

	public void setTimer_getTheStartstack2(Timer timer_getTheStartstack2) {
		this.timer_getTheStartstack2 = timer_getTheStartstack2;
	}

	public Timer getTimer_benderwalks() {
		return timer_benderwalks;
	}

	public void setTimer_benderwalks(Timer timer_benderwalks) {
		this.timer_benderwalks = timer_benderwalks;
	}

	public Timer getTimer_showNextPlayer() {
		return timer_showNextPlayer;
	}

	public void setTimer_showNextPlayer(Timer timer_showNextPlayer) {
		this.timer_showNextPlayer = timer_showNextPlayer;
	}

	public Timer getTimer_showNextDealer() {
		return timer_showNextDealer;
	}

	public void setTimer_showNextDealer(Timer timer_showNextDealer) {
		this.timer_showNextDealer = timer_showNextDealer;
	}

	public Timer getTimer_showResults() {
		return timer_showResults;
	}

	public void setTimer_showResults(Timer timer_showResults) {
		this.timer_showResults = timer_showResults;
	}
}
